package com.doudou.pay.helper.controller;

import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.doudou.pay.helper.commons.AesUtil;
import com.doudou.pay.helper.commons.JsonResult;
import com.doudou.pay.helper.commons.JsonUtil;
import com.doudou.pay.helper.commons.PayConstans;
import com.doudou.pay.helper.commons.StreamUtils;
import com.doudou.pay.helper.entities.MerchantOrderQuery;
import com.doudou.pay.helper.entities.MerchantRequestPay;
import com.doudou.pay.helper.entities.PayNotifyResult;
import com.doudou.pay.helper.entities.PayUser;
import com.doudou.pay.helper.entities.ResponsePay;
import com.doudou.pay.helper.entities.User;
import com.doudou.pay.helper.entities.UserPay;
import com.doudou.pay.helper.mapper.UserMapper;
import com.doudou.pay.helper.server.protoco.ProtocoConsts;
import com.doudou.pay.helper.service.MessageCacheService;
import com.doudou.pay.helper.service.PayService;
import com.doudou.pay.helper.service.PayUserService;
import com.doudou.pay.helper.vo.PayNotifyVo;
import com.doudou.pay.helper.websocket.WebSocketResponse;

@Controller
public class PayController {

	@Autowired
	private PayService payService;

	@Autowired
	private PayUserService payUserService;

	@Autowired
	private MessageCacheService messageCacheService;

	@Autowired
	private UserMapper userMapper;

	@RequestMapping("/userPay")
	public @ResponseBody JsonResult userPay(UserPay userPay,
			HttpSession httpSession) {
		JsonResult jsonResult = new JsonResult();

		userPay.setUserId((String) httpSession.getAttribute("userId"));
		userPay.setSessionKey((String) httpSession.getAttribute("sessionKey"));

		List<PayUser> payUsers = payUserService.getPayUserByUserId(userPay
				.getUserId());
		if (null == payUsers || payUsers.size() == 0) {
			return jsonResult.setDefine("不存在的用户");
		}

		// 判断在线客户端数量
		Map<String, Integer> onlineClientMap = payUserService
				.getOnlineAuthToken(userPay.getUserId());
		if (onlineClientMap.size() == 0) {
			return jsonResult.setDefine("客户端不在线");
		}

		if (StringUtils.isEmpty(userPay.getType())) {
			return jsonResult.setDefine("请选择支付方式");
		}

		if (userPay.getMoney() <= 0) {
			return jsonResult.setDefine("请输入金额");
		}

		WebSocketResponse response = payService.pay(userPay, onlineClientMap);
		return jsonResult.setCode(ProtocoConsts.SUCCESS)
				.setDefine(ProtocoConsts.SUCCESS_DEFINE).setResult(response);
	}

	@ResponseBody
	@RequestMapping(value = "/payresult", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE
			+ ";Charset=UTF-8")
	public JsonResult payResult(HttpServletRequest request,
			HttpServletResponse response) {
		JsonResult jsonResult = new JsonResult();
		try {
			ServletInputStream inputStream = request.getInputStream();
			String postData = StreamUtils.copyToString(inputStream,
					Charset.forName("utf-8"));

			postData = AesUtil.decrypt(postData, AesUtil.KEY);

			System.out.println("payResult:" + postData);

			PayNotifyVo payNotifyVo = JsonUtil.parseObject(postData,
					PayNotifyVo.class);
			if (StringUtils.isEmpty(payNotifyVo.getMark())) {
				return jsonResult.setDefine("无订单编号");
			}

			User user = userMapper.findByUsername(payNotifyVo.getAccount());
			if (user == null) {
				return jsonResult.setDefine("未知用户");
			}

			if (!user.getAuthToken().equals(payNotifyVo.getAccoauthTokenunt())) {
				return jsonResult.setDefine("签名不对");
			}
			// if(!payService.isExisPayOrder(authToken, payId)) {
			// return jsonResult.setDefine("无订单编号");
			// }

			if (payNotifyVo.getState() == 1
					&& payService.updatePayInfo(PayConstans.PAY_STATUS_SUCCESS,
							user, payNotifyVo.getMark(),
							payNotifyVo.getPlatformOrder(),
							payNotifyVo.getPlatformOrderStatus()) > 0) {
				return jsonResult.setCode(ProtocoConsts.SUCCESS).setDefine(
						ProtocoConsts.SUCCESS_DEFINE);
			}

		} catch (Exception e) {
			System.out.println("Exception" + e.getMessage());
			return jsonResult;
		}

		return jsonResult;
	}

	@RequestMapping("/response")
	public @ResponseBody JsonResult getResponsePay(HttpSession httpSession) {
		JsonResult jsonResult = new JsonResult();
		ResponsePay responsePay = messageCacheService
				.getResponsePay((String) httpSession.getAttribute("sessionKey"));
		if (null != responsePay) {
			messageCacheService.removeResponsePay((String) httpSession
					.getAttribute("sessionKey"));
			jsonResult.setCode(ProtocoConsts.SUCCESS).setResult(responsePay);
		}
		return jsonResult;
	}

	@RequestMapping("/{userId}/pay")
	public ModelAndView userPay(@PathVariable(value = "userId") String userId,
			HttpSession httpSession) {
		ModelAndView modelAndView = new ModelAndView("index2");
		httpSession.setAttribute("userId", userId);
		httpSession.setAttribute("sessionKey", UUID.randomUUID().toString());
		return modelAndView;
	}

	@RequestMapping("/notify/pay")
	public @ResponseBody JsonResult payNotify(int status, String payId,
			String authToken, String platformOrder, String platformOrderStatus) {
		JsonResult jsonResult = new JsonResult();
		if (StringUtils.isEmpty(payId)) {
			return jsonResult.setDefine("无订单编号");
		}

		if (!payService.isExisPayOrder(authToken, payId)) {
			return jsonResult.setDefine("无订单编号");
		}

		if (status == 1
				&& payService.updatePayInfo(PayConstans.PAY_STATUS_SUCCESS,
						null, payId, platformOrder, platformOrderStatus) > 0) {
			return jsonResult.setCode(ProtocoConsts.SUCCESS).setDefine(
					ProtocoConsts.SUCCESS_DEFINE);
		}

		if (status == -1
				&& payService.updatePayInfo(PayConstans.PAY_STATUS_NOTIFY_FAIL,
						null, payId, platformOrder, platformOrderStatus) > 0) {
			return jsonResult.setCode(ProtocoConsts.SUCCESS).setDefine(
					ProtocoConsts.SUCCESS_DEFINE);
		}

		return jsonResult;
	}

	@RequestMapping("/notify/result")
	public @ResponseBody JsonResult getNotifyResult(HttpSession httpSession) {
		JsonResult jsonResult = new JsonResult();
		PayNotifyResult payNotifyResult = messageCacheService
				.getPayNotifyResult((String) httpSession
						.getAttribute("sessionKey"));
		if (null != payNotifyResult) {
			messageCacheService.removePayNotifyResult((String) httpSession
					.getAttribute("sessionKey"));
			jsonResult.setCode(ProtocoConsts.SUCCESS)
					.setResult(payNotifyResult);
		}
		return jsonResult;
	}

	@RequestMapping("/merchantNotifyUrl")
	public @ResponseBody JsonResult putMerchantNotifyUrl(String authToken,
			String notifyAddress) {
		JsonResult jsonResult = new JsonResult();
		if (StringUtils.isEmpty(notifyAddress)) {
			return jsonResult.setDefine("无通知地址");
		}

		if (StringUtils.isEmpty(authToken)) {
			return jsonResult.setDefine("无授权码");
		}

		if (payUserService.updateNotifyUrl(authToken, notifyAddress) > 0) {
			return jsonResult.setCode(ProtocoConsts.SUCCESS).setDefine(
					ProtocoConsts.SUCCESS_DEFINE);
		}

		return jsonResult;
	}

	@RequestMapping("/qrcode")
	public @ResponseBody MerchantRequestPay merchantRequestPay(UserPay userPay) {
		MerchantRequestPay requestPay = new MerchantRequestPay(userPay);

		List<PayUser> payUsers = payUserService.getPayUserByUserId(userPay
				.getUserId());
		if (null == payUsers || payUsers.size() == 0) {
			requestPay.setCode(ProtocoConsts.FAIL);
			requestPay.setDefine("不存在的用户");
			return requestPay;
		}

		// 判断在线客户端数量
		Map<String, Integer> onlineClientMap = payUserService
				.getOnlineAuthToken(userPay.getUserId());
		if (onlineClientMap.size() == 0) {
			requestPay.setCode(ProtocoConsts.FAIL);
			requestPay.setDefine("客户端不在线");
			return requestPay;
		}

		if (StringUtils.isEmpty(userPay.getType())) {
			requestPay.setCode(ProtocoConsts.FAIL);
			requestPay.setDefine("请选择支付方式");
			return requestPay;
		}

		if (userPay.getMoney() <= 0) {
			requestPay.setCode(ProtocoConsts.FAIL);
			requestPay.setDefine("请输入金额");
			return requestPay;
		}

		userPay.setSessionKey(UUID.randomUUID().toString());
		WebSocketResponse response = payService.pay(userPay, onlineClientMap);
		if (response.getCode() != ProtocoConsts.SUCCESS) {
			requestPay.setCode(ProtocoConsts.FAIL);
			requestPay.setDefine("获取二维码失败");
			return requestPay;
		}

		// 夯住请求
		long startTime = System.currentTimeMillis();
		ResponsePay responsePay = null;
		while ((responsePay = messageCacheService.getResponsePay(userPay
				.getSessionKey())) == null
				&& System.currentTimeMillis() - startTime < 1000 * 20) {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		if (null == responsePay) {
			requestPay.setCode(0);
			requestPay.setDefine("获取二维码超时");
			return requestPay;
		}

		if (ProtocoConsts.SUCCESS == responsePay.getCode()) {
			requestPay.setCode(ProtocoConsts.SUCCESS);
			requestPay.setDefine(ProtocoConsts.SUCCESS_DEFINE);
			requestPay.setPayUrl(responsePay.getPayUrl());
			return requestPay;
		}

		requestPay.setCode(ProtocoConsts.FAIL);
		requestPay.setDefine(ProtocoConsts.FAIL_DEFINE);
		return requestPay;
	}

	@RequestMapping("/query/order")
	public @ResponseBody MerchantOrderQuery merchantRequestPay(String userId,
			String thirdPartyOrderId) {
		MerchantOrderQuery query = new MerchantOrderQuery();
		query.setUserId(userId);
		query.setRemark(thirdPartyOrderId);

		if (StringUtils.isEmpty(userId)) {
			query.setCode(ProtocoConsts.FAIL);
			query.setDefine("商户Id为空");
			return query;
		}

		if (StringUtils.isEmpty(thirdPartyOrderId)) {
			query.setCode(ProtocoConsts.FAIL);
			query.setDefine("备注信息为空");
			return query;
		}

		MerchantOrderQuery order = payService.getMerchantOrderQuery(query);
		if (null == order) {
			query.setCode(ProtocoConsts.FAIL);
			query.setDefine("查询失败");
			return query;
		}

		order.setCode(ProtocoConsts.SUCCESS);
		order.setDefine(ProtocoConsts.SUCCESS_DEFINE);
		return order;
	}

}
